<template>
    <div>
        <div class="header">
            <div class="left flex align-center ">
                <el-button size="small" :icon="ArrowLeftBold">返回</el-button>
                <div class="title">
                    【模拟直播间】直播间名称
                </div>
                <div class="tag-box">
                    <el-tag round>抖音</el-tag>
                    <el-tag round>美食</el-tag>
                    <el-tag round>数字人直播</el-tag>
                </div>
            </div>
            <div class="right">
                <el-button size="small" @click="toSetPage">直播间设置</el-button>
                <el-button size="small" @click="showDialog">开播</el-button>
            </div>
        </div>

        <div class="simulated-live grid grid-cols-2 gap-20">
            <div class="left default-scroll">
                <div>台词播报</div>
                <div>
                    {{ store.state.defaultScriptText }}
                </div>
            </div>
            <div class="right flex align-center flex-column">
                <div>
                    <el-button type="primary" text @click="getDeskApp">没有直播画面点这里</el-button>
                </div>
                <CatchScreen ref="catchScreenRef" :messageList="messageList" @updateBarrage="updateMessageList"></CatchScreen>
            </div>
        </div>
    </div>

    <el-dialog v-model="dialogVisible" title="请输入直播间链接" width="500" @close="dialogVisible = false">
        <el-input v-model="liveLink" size="small"></el-input>
        <template #footer>
            <div class="dialog-footer">
                <el-button type="primary" @click="confirmLiveLink">
                    确定
                </el-button>
            </div>
        </template>
    </el-dialog>
</template>

<script setup>
import { useAppStore } from "@/store/index"
import { onMounted, onUnmounted, reactive, ref } from "vue";
import { ElMessage } from "element-plus";
import { ipcApiRoute } from "@/api/main";
import { ipc } from "@/utils/ipcRenderer";
import { useFieldControlHooks } from "@/hooks/fieldControlHooks";
import axios from "axios";
import { ArrowLeftBold } from "@element-plus/icons-vue";
import CatchScreen from '@/components/CatchScreen/index.vue'

const { connectFieldControl, messageList } = useFieldControlHooks();

const store = useAppStore()

const path = require("path");
const fs = require("fs");

const dialogVisible = ref(false);
const liveLink = ref("");

const net = window.require("net");
const socket = new net.Socket();
// const socket = io('127.0.0.1:12345')
const servicAddress = "127.0.0.1";
const port = "12345";
const num = ref(0);

const catchScreenRef = ref()
const timer = ref(null);
const queryAudioData = reactive({
    data: {},
});
const message = ref("");
const loading = ref(false);
const folderPath =
    "D:\\dh-runtime/wav2lip/wav2lip/realtime/rtmp_server/push_stream/face_npy/test1";
const fileName = "final_output.txt";

// 初始化数字人指令
const INIT_DIGITAL = ref("INIT_DIGITAL_HUMAN:test1:wav2lip");

// 启动本地播放器指令
const START_LOCAL = "START_STREAMING:local";

// 音频指令
const AUDIO_DIRECT = `TRANSMIT_AUDIO_FILE:${store.state.defaultAudio}`;

// 生成npy文件
const handleNpyBat = () => {
    const batPath = "D:\\ms-ge.bat";
    const videoPath = "D:\\test1.mp4";
    const outfolderName = "test1";

    const isExitOutTxt = checkIfFileExists([folderPath], fileName);
    console.log("isExitOutTxt----", isExitOutTxt);

    if (!isExitOutTxt) {
        const d = `${batPath} ${videoPath} ${outfolderName}`;
        ipc
            .invoke(ipcApiRoute.openBatFile, { batPath, videoPath, outfolderName })
            .then((res) => {
                console.log("handleNpyBat----->", res);
                loading.value = true;
                checkIsExist();
            });
    }
};

const checkIsExist = () => {
    timer.value = setInterval(() => {
        checkIfFileExists({ folderPath, fileName });
    }, 3000);

    // ipc.invoke(ipcApiRoute.checkFileExists, { folderPath, fileName }).then(res => {
    //     console.log("checkIsExist----->",res)
    //     // if (!res) {
    //     //     checkIsExist()
    //     // }
    // })
};

// 检查文件是否存在的函数
const checkIfFileExists = (folderPaths, filename) => {
    return folderPaths.every((folderPath) => {
        const filePath = path.join(folderPath, filename);
        return fs.existsSync(filePath);
    });
};

const initDigitalHuman = () => {
    loading.value = true;
    const directs = [INIT_DIGITAL.value, START_LOCAL, AUDIO_DIRECT];
    if (directs[num.value]) {
        sendDirect(directs[num.value]);
    }

    // if(num.value == 0){
    //     sendDirect(INIT_DIGITAL)
    // }else if(num.value == 1){
    //     sendDirect(START_LOCAL)
    // }else if(num.value == 2){
    //     sendDirect(AUDIO_DIRECT)
    // }
};

const socketInit = () => {
    socket.connect(port, servicAddress, () => {
        console.log(
            "连接socket成功:" + num.value + ", socket地址" + servicAddress + ":" + port
        );
        if (num.value >= 0 && num.value < 3) {
            initDigitalHuman();
        }

        console.log("queryAudioData", queryAudioData.data);
        if (queryAudioData.data) {
            if (+queryAudioData.data.pushqueue * 2 <= 4) {
                // 可以继续发送音频
                sendAudio();
                // isSendAudio.value = true
            }
        }
    });
};

const sendDirect = (message) => {
    socket.write(message);
    console.log(`发送消息--${message}--成功---`);
};

const socketData = () => {
    socket.on("data", (data) => {
        console.log("-----------------------");
        console.log("接收到数据:");
        const rstObj = parseBufferToObjectWithRegex(data);
        console.log(rstObj);
        const is200 = rstObj.statecode == "200";
        loading.value = false;

        if (is200) {
            num.value += 1;
            if (rstObj.pushqueue) {
                Object.assign(queryAudioData.data, rstObj);
            } else {
                queryAudioData.data = {};
            }
            console.log("queryAudioData=======", queryAudioData.data);
        } else {
            ElMessage.error(`接受socket返回消息：${data.toString()}`);
        }
    });
};

const parseBufferToObjectWithRegex = (buffer) => {
    // 将 buffer 转换为字符串并去除首尾空白字符
    let dataString = buffer.toString("utf-8").trim();

    // 正则表达式匹配所有键值对 (键和值之间用 ":" 分隔，允许值为空)
    let resultObject = {};
    let regex = /\s*([^:]+)\s*:\s*([^:]*?)\s*(?=\s*:|$)/g; // 允许值为空
    let match;

    // 使用 exec 循环查找所有匹配的键值对
    while ((match = regex.exec(dataString)) !== null) {
        // 如果值为空，则给定空字符串作为默认值
        resultObject[match[1].trim()] = match[2].trim() || ""; // 如果没有值，设置为 ""
    }

    return resultObject;
};

const socketClose = () => {
    socket.on("close", () => {
        console.log("链接关闭:", num.value);
        // if(num.value > 0 && num.value < 3){
        socketInit();
        // }else{
        //
        // }
        if (num.value == 3) {
            loading.value = false;
            getDeskApp()
        }
    });
};

// 确认开播
const confirmLiveLink = async () => {
    if(!liveLink.value){
        ElMessage.error("请输入直播间地址")
        return
    }
    dialogVisible.value = true
    console.log("liveLink.value---", liveLink.value)
    try {
        await connectFieldControl(liveLink.value)
        dialogVisible.value = false

    } catch (error) {
        
    }
}

const getDeskApp = () => {
    catchScreenRef.value.getDeskApp()
}

const socketError = () => {
    socket.on("error", (err) => {
        console.log("socketError----->", err);

        if (err.code === "ECONNRESET") {
            console.error("Connection reset by peer");
            // 在这里可以实现重试逻辑或其他错误处理
        } else {
            console.error("Socket error:", err);
        }
    });
};

// 发送文本转语音
const sendText = () => {
    if (!message.value.trim()) {
        ElMessage.error("请输入文本内容");
        return;
    }
    const audio_save_filename = `音频${audioList.value.length + 1}.wav`;
    axios
        .post("http://127.0.0.1:9670/synthesize", {
            models_name: "meiqi", // 声音模型
            audio_save_path: "D:\\", // 保存路径
            audio_save_filename: audio_save_filename, // 保存文件名
            text: message.value, // 文本内容
            length_scale: 1.1, // 语速
            comma_pause: 0.3, // 逗号停顿
            period_pause: 0.5, // 句号停顿
            priority: 1, //0是代表高级 1是代表低级 默认是1
        })
        .then((res) => {
            console.log("sendText----->", res);
            if (res.status == 200) {
                const { data } = res;
                const audioItem = {
                    path: data.audio_path,
                    name: audio_save_filename,
                };
                const AUDIO_DIRECT = `TRANSMIT_AUDIO_FILE:${data.audio_path}`;
                console.log("发送音频指令sendText：", AUDIO_DIRECT);
                sendDirect(AUDIO_DIRECT);
                // audioList.value.push(audioItem)
                message.value = "";
            }
        });
};

// 
const updateMessageList = (obj) => {
    console.log("updateMessageList----->", obj)
    messageList.push(obj)
}
const toSetPage = () => {
    router.push({
        name: "LiveRoomSet",
    });
};

const showDialog = () => {
    dialogVisible.value = true;
};

onMounted(() => {
    // 执行bat脚本，生成npy文件
    handleNpyBat();
    // socket连接
    socketInit();
    socketData();
    socketClose();
    socketError();
})
</script>

<style lang="less" scoped>
.header {
    width: 100%;
    height: 50px;
    background-color: @bg-default;
    color: @color-white;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-left: 20px;
    box-sizing: border-box;
    margin-bottom: 20px;
    padding-right: 20px;

    .title {
        margin: 0 20px;
        color: @color-white;
    }

    .tag-box {
        .el-tag {
            margin-right: 10px;
        }
    }
}

.simulated-live {
    width: 100%;
    height: calc(100vh - 160px);

    .left,
    .right {
        color: @color-white;
        background-color: @bg-default;
        padding: 10px;
        box-sizing: border-box;
    }

    .left {
        height: 100%;
        overflow-y: auto;
    }
}
</style>